package org.genko.model;

import java.io.Serializable;
import org.w3c.dom.*;
/***
 * Represents an object node which is Member of a Model
 * @author Israel Chapa
 */
public interface MemberObject extends Serializable
{
	/**
	 * Returns the Type of this MemberObject
	 * @return the Type of this MemberObject
	 */
	MemberType getMemberType();
	
	/**
	 * Returns the Definition of this MemberObject
	 * @return the Definition of this MemberObject
	 */
	MemberDefinition getMemberDefinition();

	/**
	 * Returns the Owner Member of this MemberObject
	 * @return the Owner Member of this MemberObject
	 */
	MemberObject getOwner();

	/**
	 * Returns the Scheme of this MemberObject, or null if it has not owner
	 * @return The Scheme of this MemberObject
	 */
	Scheme getScheme();

	/**
	 * Returns the Id of this Member which is unique per Member Owner
	 * @return The Id of this Member
	 */
	String getMemberId();

	/**
	 * Returns the Name of this MemberObject
	 * @return the Name of this MemberObject
	 */
	String getMemberName();

	/**
	 * Sets the name of this Member
	 * @param name The name of the Member
	 * @throws MemberException if the operation is not allowed
	 */
	void setMemberName(String name);

	/**
	 * Gets the index of this attached member, or -1 if is not attached
	 * @return The index of this attached member, or -1 if is not attached
	 */
	int getMemberIndex();

	/**
	 * Gets the Collection of Element Members of this Object
	 * @return the Collection of Element Members of this Object
	 */
	MemberCollection getElements();

	/**
	 * Gets the Collection of Attribute Members of this Object
	 * @return The Collection of Attribute Members of this Object
	 */
	MemberCollection getAttributes();

	/**
	 * @return true if this object is read only, false otherwise
	 */
	boolean isReadOnly();

	/**
	 * @return true if this object doesn't have name, false otherwise
	 */
	boolean isAnonymous();

	/**
	 * @return true if this object is attached to its owner, false otherwise
	 */
	boolean isAttached();

	/**
	 * @return true if this object has a value, false otherwise
	 */
	boolean hasValue();

	/**
	 * @return true if this object is an attribute, false otherwise
	 */
	boolean isAttribute();

	/**
	 * @return true if this object is an element, false otherwise
	 */
	boolean isElement();
	
	/**
	 * @return true if this object is a reference to oher member, false otherwise
	 */
	boolean isReference();

	/**
	 * @return The representation of the path to this object in the model
	 */
	String getMemberPath();

	/**
	 * @return The referenced object by this object, or null if it is not a reference
	 */
	MemberObject getReferenceObject();

	/**
	 * @return The value of this Object
	 */
	Object getValue();

	/**
	 * Sets the value of this Object
	 * @param value The value to set
	 */
	void setValue(Object value);

	/**
	 * Gets the first MemberObject associated with the given member path
	 * @param memberPath The member path
	 * @return the first MemberObject associated with the given member path, or null if it was not found
	 */
	MemberObject getMember(String memberPath);

	/**
	 * Gets the Collection of Members matched for the given member path
	 * @param memberPath The member path
	 * @return the Collection of Members matched for the given member path
	 */
	MemberCollection getMembers(String memberPath);

	/**
	 * Makes a detached deep copy of this object, the owner will be the same of this object but isAttached() will return false
	 * @return A deep copy of this object
	 */
	MemberObject cloneMember();
	
	/**
	 * Attaches an element member to this object of the given type
	 * @param type The type of the member to attach
	 * @return The new attached object
	 */
	MemberObject attach(MemberType type);

	/**
	 * Attaches an element member to this object after the last element attached
	 * @param object The element to attach
	 * @return The attached object
	 */
	MemberObject attach(MemberObject object);

	/**
	 * Attaches a member to this object after the last attribute attached
	 * @param object The attribute to attach
	 * @return The attached object
	 */
	MemberObject attachAttribute(MemberObject object);

	/**
	 * Attaches a member before the referenced object
	 * @param object The object to attach
	 * @param refObj The reference object
	 * @return The attached object
	 */
	MemberObject attachBefore(MemberObject object, MemberObject refObj);
	
	/**
	 * Detaches a member from this object
	 * @param object The object to detach
	 * @return The detached object
	 */
	MemberObject detach(MemberObject object);

	/**
	 * Replaces an attached member with another
	 * @param newMember The new object to attach
	 * @param oldMember The object to replace
	 * @return The detached old member
	 */
	MemberObject replaceMember(MemberObject newMember, MemberObject oldMember);

	/**
	 * Swaps the position of 2 attached members
	 * @param o1 First member to swap
	 * @param o2 Second member to swap
	 */
	void swapMembers(MemberObject o1, MemberObject o2);
	
	/**
	 * Adds a handler which will receive events from this object
	 * @param handler The handler to add
	 */
	void addEventHandler(MemberEventHandler handler);

	/**
	 * Removes a registered handler
	 * @param handler The handler to remove
	 */
	void removeEventHandler(MemberEventHandler handler);

	/**
	 * Creates a new node based on this member object
	 * @param doc The document owner of the node
	 * @return The created node
	 */
	Node toXmlNode(Document doc);
}